Atbloķējiet FastAPI jaudu efektīvai daudzdaļu veidlapu failu augšupielādei. Šī visaptverošā rokasgrāmata aptver labāko praksi, kļūdu apstrādi un papildu paņēmienus globāliem izstrādātājiem.
FastAPI failu augšupielādes apgūšana: padziļināts ieskats Multipart veidlapu apstrādē
Mūsdienu tīmekļa lietojumprogrammās spēja apstrādāt failu augšupielādes ir būtiska prasība. Neatkarīgi no tā, vai lietotāji iesniedz profila attēlus, apstrādes dokumentus vai koplietošanas datnes, izturīgi un efektīvi failu augšupielādes mehānismi ir ļoti svarīgi. FastAPI, augstas veiktspējas Python tīmekļa ietvars, izceļas šajā jomā, piedāvājot vienkāršotus veidus, kā pārvaldīt multipart veidlapu datus, kas ir standarts failu sūtīšanai, izmantojot HTTP. Šī visaptverošā rokasgrāmata palīdzēs jums izprast FastAPI failu augšupielādes sarežģītību, sākot no pamata ieviešanas līdz papildu apsvērumiem, nodrošinot, ka varat droši izveidot jaudīgas un mērogojamas API globālai auditorijai.
Multipart veidlapu datu izpratne
Pirms iedziļināties FastAPI ieviešanā, ir svarīgi saprast, kas ir multipart veidlapu dati. Kad tīmekļa pārlūkprogramma iesniedz veidlapu, kurā ir faili, tā parasti izmanto atribūtu enctype="multipart/form-data". Šis kodēšanas veids sadala veidlapas iesniegumu vairākās daļās, katrai ar savu satura veidu un informāciju par izvietojumu. Tas ļauj vienā HTTP pieprasījumā pārsūtīt dažāda veida datus, tostarp teksta laukus, teksta laukus un bināros failus.
Katra daļa multipart pieprasījumā sastāv no:
- Content-Disposition galvene: norāda veidlapas lauka nosaukumu (
name) un failiem sākotnējo faila nosaukumu (filename). - Content-Type galvene: norāda daļas MIME veidu (piemēram,
text/plain,image/jpeg). - Ķermenis: faktiskie dati šai daļai.
FastAPI pieeja failu augšupielādei
FastAPI izmanto Python standarta bibliotēku un nemanāmi integrējas ar Pydantic datu validācijai. Failu augšupielādei tas izmanto UploadFile tipu no fastapi moduļa. Šī klase nodrošina ērtu un drošu saskarni augšupielādēto failu datu piekļuvei.
Pamata failu augšupielādes ieviešana
Sāksim ar vienkāršu piemēru par to, kā izveidot galapunktu FastAPI, kas pieņem vienu failu augšupielādi. Mēs izmantosim funkciju File no fastapi, lai deklarētu faila parametru.
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async def create_file(file: UploadFile):
return {"filename": file.filename, "content_type": file.content_type}
Šajā piemērā:
- Mēs importējam
FastAPI,FileunUploadFile. - Galapunkts
/files/ir definēts kāPOSTpieprasījums. - Parametrs
fileir anotēts arUploadFile, norādot, ka tas sagaida faila augšupielādi. - Galapunkta funkcijas iekšpusē mēs varam piekļūt augšupielādētā faila rekvizītiem, piemēram,
filenameuncontent_type.
Kad klients nosūta POST pieprasījumu uz /files/ ar pievienotu failu (parasti, izmantojot veidlapu ar enctype="multipart/form-data"), FastAPI automātiski apstrādās parsēšanu un nodrošinās UploadFile objektu. Pēc tam varat mijiedarboties ar šo objektu.
Augšupielādēto failu saglabāšana
Bieži vien jums būs jāsaglabā augšupielādētais fails diskā vai jāapstrādā tā saturs. Objekts UploadFile nodrošina metodes tam:
read(): Nolasa visu faila saturu atmiņā kā baitus. Izmantojiet to mazākiem failiem.write(content: bytes): Ieraksta baitus failā.seek(offset: int): Maina pašreizējo faila pozīciju.close(): Aizver failu.
Ir svarīgi apstrādāt failu darbības asinhroni, īpaši, ja strādājat ar lieliem failiem vai I/O saistītiem uzdevumiem. FastAPI UploadFile atbalsta asinhronas darbības.
from fastapi import FastAPI, File, UploadFile
import shutil
app = FastAPI()
@app.post("/files/save/")
async def save_file(file: UploadFile = File(...)):
file_location = f"./uploads/{file.filename}"
with open(file_location, "wb+") as file_object:
file_object.write(await file.read())
return {"info": f"file '{file.filename}' saved at '{file_location}'"}
Šajā uzlabotajā piemērā:
- Mēs izmantojam
File(...), lai norādītu, ka šis parametrs ir obligāts. - Mēs norādām lokālu ceļu, kur fails tiks saglabāts. Pārliecinieties, vai pastāv direktorija
uploads. - Mēs atveram galamērķa failu binārā rakstīšanas režīmā (`"wb+"`).
- Mēs asinhroni nolasām augšupielādētā faila saturu, izmantojot
await file.read(), un pēc tam ierakstām to lokālajā failā.
Piezīme: Visa faila nolasīšana atmiņā ar await file.read() varētu būt problemātiska ļoti lieliem failiem. Šādos gadījumos apsveriet faila satura straumēšanu.
Failu satura straumēšana
Lieliem failiem visa satura nolasīšana atmiņā var izraisīt pārmērīgu atmiņas patēriņu un iespējamas kļūdas par atmiņas trūkumu. Atmiņas ziņā efektīvāka pieeja ir faila straumēšana pa daļām. Funkcija shutil.copyfileobj ir lieliska šim nolūkam, taču mums tā ir jāpielāgo asinhronām darbībām.
from fastapi import FastAPI, File, UploadFile
import aiofiles # Install using: pip install aiofiles
app = FastAPI()
@app.post("/files/stream/")
async def stream_file(file: UploadFile = File(...)):
file_location = f"./uploads/{file.filename}"
async with aiofiles.open(file_location, "wb") as out_file:
content = await file.read()
await out_file.write(content)
return {"info": f"file '{file.filename}' streamed and saved at '{file_location}'"}
Izmantojot aiofiles, mēs varam efektīvi straumēt augšupielādētā faila saturu uz galamērķa failu, neielādējot visu failu atmiņā vienlaikus. await file.read() šajā kontekstā joprojām nolasa visu failu, taču aiofiles apstrādā rakstīšanu efektīvāk. Lai patiesi straumētu pa daļām, izmantojot UploadFile, parasti iterētu await file.read(chunk_size), taču aiofiles.open un await out_file.write(content) ir izplatīts un efektīvs modelis saglabāšanai.
Konkrētāka straumēšanas pieeja, izmantojot segmentēšanu:
from fastapi import FastAPI, File, UploadFile
import aiofiles
app = FastAPI()
CHUNK_SIZE = 1024 * 1024 # 1MB chunk size
@app.post("/files/chunked_stream/")
async def chunked_stream_file(file: UploadFile = File(...)):
file_location = f"./uploads/{file.filename}"
async with aiofiles.open(file_location, "wb") as out_file:
while content := await file.read(CHUNK_SIZE):
await out_file.write(content)
return {"info": f"file '{file.filename}' chunked streamed and saved at '{file_location}'"}
Šis `chunked_stream_file` galapunkts nolasa failu 1 MB lielos segmentus un ieraksta katru segmentu izvades failā. Šis ir visefektīvākais veids, kā apstrādāt potenciāli ļoti lielus failus.
Vairāku failu augšupielādes apstrāde
Tīmekļa lietojumprogrammām bieži vien ir nepieciešams, lai lietotāji vienlaikus augšupielādētu vairākus failus. FastAPI padara to vienkāršu.Failu saraksta augšupielāde
Varat pieņemt failu sarakstu, anotējot savu parametru ar UploadFile sarakstu.
from fastapi import FastAPI, File, UploadFile, Form
from typing import List
app = FastAPI()
@app.post("/files/multiple/")
async def create_multiple_files(
files: List[UploadFile] = File(...)
):
results = []
for file in files:
# Process each file, e.g., save it
file_location = f"./uploads/{file.filename}"
with open(file_location, "wb+") as file_object:
file_object.write(await file.read())
results.append({"filename": file.filename, "content_type": file.content_type, "saved_at": file_location})
return {"files_processed": results}
Šajā scenārijā klientam ir jānosūta vairākas daļas ar vienu un to pašu veidlapas lauka nosaukumu (piemēram, `files`). FastAPI apkopos tos Python UploadFile objektu sarakstā.
Failu un citu veidlapu datu sajaukšana
Ir ierasts, ka veidlapās ir gan failu lauki, gan parasti teksta lauki. FastAPI to apstrādā, ļaujot deklarēt citus parametrus, izmantojot standarta tipu anotācijas, kā arī Form veidlapas laukiem, kas nav faili.
from fastapi import FastAPI, File, UploadFile, Form
from typing import List
app = FastAPI()
@app.post("/files/mixed/")
async def upload_mixed_data(
description: str = Form(...),
files: List[UploadFile] = File(...) # Accepts multiple files with the name 'files'
):
results = []
for file in files:
# Process each file
file_location = f"./uploads/{file.filename}"
with open(file_location, "wb+") as file_object:
file_object.write(await file.read())
results.append({"filename": file.filename, "content_type": file.content_type, "saved_at": file_location})
return {
"description": description,
"files_processed": results
}
Izmantojot tādus rīkus kā Swagger UI vai Postman, jūs norādīsit description kā parastu veidlapas lauku un pēc tam pievienosit vairākas daļas laukam files, katrai no tām iestatot atbilstošo attēla/dokumenta tipu.
Papildu funkcijas un labākā prakse
Papildus pamata failu apstrādei vairākas papildu funkcijas un labākā prakse ir ļoti svarīgas, lai izveidotu izturīgas failu augšupielādes API.
Failu lieluma ierobežojumi
Neierobežotas failu augšupielādes atļaušana var izraisīt pakalpojumatteices uzbrukumus vai pārmērīgu resursu patēriņu. Lai gan FastAPI pats pēc noklusējuma nepiemēro stingrus ierobežojumus sistēmas līmenī, jums jāievieš pārbaudes:
- Lietojumprogrammas līmenī: Pārbaudiet faila lielumu pēc tā saņemšanas, bet pirms apstrādes vai saglabāšanas.
- Tīmekļa servera/starpniekservera līmenī: Konfigurējiet savu tīmekļa serveri (piemēram, Nginx, Uvicorn ar darbiniekiem), lai noraidītu pieprasījumus, kas pārsniedz noteiktu kravas lielumu.
Lietojumprogrammas līmeņa lieluma pārbaudes piemērs:
from fastapi import FastAPI, File, UploadFile, HTTPException
app = FastAPI()
MAX_FILE_SIZE_MB = 10
MAX_FILE_SIZE_BYTES = MAX_FILE_SIZE_MB * 1024 * 1024
@app.post("/files/limited_size/")
async def upload_with_size_limit(file: UploadFile = File(...)):
if len(await file.read()) > MAX_FILE_SIZE_BYTES:
raise HTTPException(status_code=400, detail=f"File is too large. Maximum size is {MAX_FILE_SIZE_MB}MB.")
# Reset file pointer to read content again
await file.seek(0)
# Proceed with saving or processing the file
file_location = f"./uploads/{file.filename}"
with open(file_location, "wb+") as file_object:
file_object.write(await file.read())
return {"info": f"File '{file.filename}' uploaded successfully."}
Svarīgi: Pēc faila nolasīšanas, lai pārbaudītu tā lielumu, jums jāizmanto await file.seek(0), lai atiestatītu faila rādītāju uz sākumu, ja plānojat vēlreiz nolasīt tā saturu (piemēram, lai to saglabātu).
Atļautie failu tipi (MIME tipi)
Augšupielādes ierobežošana noteiktiem failu tipiem uzlabo drošību un nodrošina datu integritāti. Varat pārbaudīt objekta UploadFile atribūtu content_type.
from fastapi import FastAPI, File, UploadFile, HTTPException
app = FastAPI()
ALLOWED_FILE_TYPES = {"image/jpeg", "image/png", "application/pdf"}
@app.post("/files/restricted_types/")
async def upload_restricted_types(file: UploadFile = File(...)):
if file.content_type not in ALLOWED_FILE_TYPES:
raise HTTPException(status_code=400, detail=f"Unsupported file type: {file.content_type}. Allowed types are: {', '.join(ALLOWED_FILE_TYPES)}")
# Proceed with saving or processing the file
file_location = f"./uploads/{file.filename}"
with open(file_location, "wb+") as file_object:
file_object.write(await file.read())
return {"info": f"File '{file.filename}' uploaded successfully and is of an allowed type."}
Lai veiktu spēcīgāku tipu pārbaudi, īpaši attēliem, varat apsvērt iespēju izmantot tādas bibliotēkas kā Pillow, lai pārbaudītu faila faktisko saturu, jo MIME tipus dažreiz var viltot.
Kļūdu apstrāde un lietotāju atsauksmes
Sniedziet lietotājam skaidrus un rīcībspējīgus kļūdu ziņojumus. Izmantojiet FastAPI HTTPException standarta HTTP kļūdu atbildēm.
- Fails nav atrasts/trūkst: Ja obligātais faila parametrs nav nosūtīts.
- Faila lielums pārsniegts: Kā parādīts lieluma ierobežojuma piemērā.
- Nederīgs faila tips: Kā parādīts tipu ierobežojuma piemērā.
- Servera kļūdas: Problēmām faila saglabāšanas vai apstrādes laikā (piemēram, disks ir pilns, atļauju kļūdas).
Drošības apsvērumi
Failu augšupielādes rada drošības riskus:
- Ļaunprātīgi faili: Izpildāmu failu (
.exe,.sh) vai skriptu augšupielāde, kas maskēti kā citi failu tipi. Vienmēr validējiet failu tipus un apsveriet iespēju skenēt augšupielādētos failus, lai atrastu ļaunprogrammatūru. - Ceļa šķērsošana: Sanitizējiet failu nosaukumus, lai novērstu uzbrucējiem augšupielādēt failus neatļautās direktorijās (piemēram, izmantojot tādus failu nosaukumus kā
../../etc/passwd). FastAPIUploadFileapstrādā pamata failu nosaukumu sanitizāciju, taču ir ieteicams papildu piesardzība. - Pakalpojuma atteikums: Ieviesiet failu lieluma ierobežojumus un, iespējams, ātruma ierobežojumus augšupielādes galapunktos.
- Starpvietņu skriptēšana (XSS): Ja failu nosaukumus vai failu saturu rādāt tieši tīmekļa lapā, pārliecinieties, vai tie ir pareizi atcelti, lai novērstu XSS uzbrukumus.
Labākā prakse: Saglabājiet augšupielādētos failus ārpus sava tīmekļa servera dokumentu saknes un pasniedziet tos, izmantojot īpašu galapunktu ar atbilstošām piekļuves kontroles iespējām, vai izmantojiet satura piegādes tīklu (CDN).
Pydantic modeļu izmantošana ar failu augšupielādēm
Lai gan UploadFile ir primārais fails, varat integrēt failu augšupielādes Pydantic modeļos, lai iegūtu sarežģītākas datu struktūras. Tomēr tiešie failu augšupielādes lauki standarta Pydantic modeļos nav dabiski atbalstīti multipart veidlapām. Tā vietā parasti saņemat failu kā atsevišķu parametru un pēc tam, iespējams, apstrādājat to formātā, ko var saglabāt vai validēt Pydantic modelis.
Izplatīts modelis ir Pydantic modelis metadatiem un pēc tam faila saņemšana atsevišķi:
from fastapi import FastAPI, File, UploadFile, Form
from pydantic import BaseModel
from typing import Optional
class UploadMetadata(BaseModel):
title: str
description: Optional[str] = None
app = FastAPI()
@app.post("/files/model_metadata/")
async def upload_with_metadata(
metadata: str = Form(...), # Receive metadata as a JSON string
file: UploadFile = File(...)
):
import json
try:
metadata_obj = UploadMetadata(**json.loads(metadata))
except json.JSONDecodeError:
raise HTTPException(status_code=400, detail="Invalid JSON format for metadata")
except Exception as e:
raise HTTPException(status_code=400, detail=f"Error parsing metadata: {e}")
# Now you have metadata_obj and file
# Proceed with saving file and using metadata
file_location = f"./uploads/{file.filename}"
with open(file_location, "wb+") as file_object:
file_object.write(await file.read())
return {
"message": "File uploaded successfully with metadata",
"metadata": metadata_obj,
"filename": file.filename
}
Šajā modelī klients nosūta metadatus kā JSON virkni veidlapas laukā (piemēram, metadata) un failu kā atsevišķu multipart daļu. Pēc tam serveris parsē JSON virkni Pydantic objektā.
Lielas failu augšupielādes un segmentēšana
Ļoti lieliem failiem (piemēram, gigabaitiem) pat straumēšana var sasniegt tīmekļa servera vai klienta puses ierobežojumus. Uzlabotāka metode ir segmentētas augšupielādes, kur klients sadala failu mazākos gabalos un augšupielādē tos secīgi vai paralēli. Pēc tam serveris saliek šos segmentus. Parasti tas prasa pielāgotu klienta puses loģiku un servera galapunktu, kas paredzēts segmentu pārvaldībai (piemēram, segmentu identificēšanai, pagaidu krātuvei un galīgajai montāžai).
Lai gan FastAPI nenodrošina iebūvētu atbalstu klienta iniciētām segmentētām augšupielādēm, varat ieviest šo loģiku savos FastAPI galapunktos. Tas ietver tādu galapunktu izveidi, kas:
- Saņem atsevišķus failu segmentus.
- Saglabā šos segmentus pagaidu krātuvē, iespējams, ar metadatiem, kas norāda to secību un kopējo segmentu skaitu.
- Nodrošina galapunktu vai mehānismu, lai signalizētu, kad visi segmenti ir augšupielādēti, aktivizējot atkārtotas montāžas procesu.
Šis ir sarežģītāks pasākums, un tas bieži ietver JavaScript bibliotēkas klienta pusē.
Internacionalizācijas un globalizācijas apsvērumi
Veidojot API globālai auditorijai, failu augšupielādēm ir nepieciešama īpaša uzmanība:
- Failu nosaukumi: Lietotāji visā pasaulē failu nosaukumos var izmantot rakstzīmes, kas nav ASCII (piemēram, akcentus, ideogrammas). Pārliecinieties, vai jūsu sistēma pareizi apstrādā un saglabā šos failu nosaukumus. UTF-8 kodēšana parasti ir standarta, taču dziļai saderībai var būt nepieciešama rūpīga kodēšana/dekodēšana un sanitizācija.
- Failu lieluma vienības: Lai gan MB un GB ir izplatīti, atcerieties, kā lietotāji uztver failu lielumus. Ir svarīgi parādīt ierobežojumus lietotājam draudzīgā veidā.
- Satura tipi: Lietotāji var augšupielādēt failus ar retākiem MIME tipiem. Pārliecinieties, vai jūsu atļauto tipu saraksts ir visaptverošs vai pietiekami elastīgs jūsu lietošanas gadījumam.
- Reģionālie noteikumi: Ievērojiet datu rezidences likumus un noteikumus dažādās valstīs. Augšupielādēto failu saglabāšanai var būt nepieciešama atbilstība šiem noteikumiem.
- Lietotāja saskarne: Klienta puses saskarne failu augšupielādei ir jābūt intuitīvai un jāatbalsta lietotāja valoda un lokalizācija.
Rīki un bibliotēkas testēšanai
Failu augšupielādes galapunktu testēšana ir ļoti svarīga. Šeit ir daži izplatīti rīki:
- Swagger UI (interaktīva API dokumentācija): FastAPI automātiski ģenerē Swagger UI dokumentāciju. Varat tieši pārbaudīt failu augšupielādes no pārlūkprogrammas saskarnes. Atrodiet faila ievades lauku un noklikšķiniet uz pogas "Izvēlēties failu".
- Postman: Populārs API izstrādes un testēšanas rīks. Lai nosūtītu failu augšupielādes pieprasījumu:
- Iestatiet pieprasījuma metodi uz POST.
- Ievadiet API galapunkta URL.
- Atveriet cilni "Ķermenis".
- Atlasiet "form-data" kā tipu.
- Atslēgas-vērtības pāros ievadiet sava faila parametra nosaukumu (piemēram,
file). - Mainiet tipu no "Teksts" uz "Fails".
- Noklikšķiniet uz "Izvēlēties failus", lai atlasītu failu no savas lokālās sistēmas.
- Ja jums ir citi veidlapas lauki, pievienojiet tos līdzīgi, saglabājot to tipu kā "Teksts".
- Nosūtiet pieprasījumu.
- cURL: Komandrindas rīks HTTP pieprasījumu veikšanai.
- Vienam failam:
curl -X POST -F "file=@/path/to/your/local/file.txt" http://localhost:8000/files/ - Vairākiem failiem:
curl -X POST -F "files=@/path/to/file1.txt" -F "files=@/path/to/file2.png" http://localhost:8000/files/multiple/ - Jauktiem datiem:
curl -X POST -F "description=My description" -F "files=@/path/to/file.txt" http://localhost:8000/files/mixed/ - Python
requestsbibliotēka: Programmatiskai testēšanai.
import requests
url = "http://localhost:8000/files/save/"
files = {'file': open('/path/to/your/local/file.txt', 'rb')}
response = requests.post(url, files=files)
print(response.json())
# For multiple files
url_multiple = "http://localhost:8000/files/multiple/"
files_multiple = {
'files': [('file1.txt', open('/path/to/file1.txt', 'rb')),
('image.png', open('/path/to/image.png', 'rb'))]
}
response_multiple = requests.post(url_multiple, files=files_multiple)
print(response_multiple.json())
# For mixed data
url_mixed = "http://localhost:8000/files/mixed/"
data = {'description': 'Test description'}
files_mixed = {'files': open('/path/to/another_file.txt', 'rb')}
response_mixed = requests.post(url_mixed, data=data, files=files_mixed)
print(response_mixed.json())
Secinājums
FastAPI nodrošina jaudīgu, efektīvu un intuitīvu veidu, kā apstrādāt multipart failu augšupielādes. Izmantojot UploadFile tipu un asinhrono programmēšanu, izstrādātāji var izveidot izturīgas API, kas nemanāmi integrē failu apstrādes iespējas. Atcerieties noteikt drošību kā prioritāti, ieviest atbilstošu kļūdu apstrādi un apsvērt globālas lietotāju bāzes vajadzības, risinot tādus aspektus kā failu nosaukumu kodēšana un atbilstība tiesību aktiem.
Neatkarīgi no tā, vai veidojat vienkāršu attēlu koplietošanas pakalpojumu vai sarežģītu dokumentu apstrādes platformu, FastAPI failu augšupielādes funkciju apgūšana būs nozīmīgs ieguvums. Turpiniet izpētīt tā iespējas, ieviest labāko praksi un nodrošināt izcilu lietotāja pieredzi savai starptautiskajai auditorijai.